<?php
/**
 * Created by PhpStorm.
 * User: ship
 * Date: 2024/12/26
 * Time: 13:34
 */

namespace ShipSun\LaravelSignature;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;

/**
 * Class SignatureMiddleware
 * @package ShipSun\LaravelSignature
 */
class SignatureMiddleware
{
    /**
     * @var Signature
     */
    public $signature;
    /**
     * @var $signatureStr
     */
    public $signatureStr;
    public static $enable = false;
    public static $sign_key = '123456';
    /**
     * @var array
     */
    public static $close_path = ['/login'];

    public function __construct(Signature $signature, SigningStr $signatureStr)
    {
        $this->signature = $signature;
        $this->signatureStr = $signatureStr;
    }

    /**
     * @param Request $request
     * @param Closure $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        if ($this->isSign($request)) {
            $signStr = $this->signStr($request);
            if (!$this->signature->driver('hmacSha')->verify($signStr, $this->sign($request))) {
                throw new Exception(Exception::VERIFY_FAIL);
            }
        }

        return $next($request);
    }

    protected function isSign(Request $request)
    {
        $key = $request->headers->get('sign_key');
        if (static::$enable || $key == static::$sign_key) {
            return !$this->checkPath($request->getPathInfo());
        }
        return false;
    }

    protected function checkPath($path)
    {
        $path = '/' . trim($path, '/');
        if (in_array($path, static::$close_path)) {
            return true;
        }
        return false;
    }

    protected function sign(Request $request)
    {
        return $request->headers->get('signature');
    }

    protected function signStr(Request $request)
    {
        foreach ($request->headers->all() as $key => $value) {
            $data[$key] = implode(',', $value);
        }
        $data['method'] = strtolower($request->method());
        $data['request_uri'] = $request->getRequestUri();
        return $this->signatureStr->create($data);
    }
}